package functionalEnrichment.semanticSimilarity.semanticSimilarityCalculator.units;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */



import java.util.ArrayList;
import java.util.List;
import functionalEnrichment.semanticSimilarity.semanticSimilarityCalculator.graph.DAG;
import java.util.HashSet;


/**
 * This class extends the DAG class (see the graph package).
 * A GoTerm is part of a DAG (directed acyclic graph)
 * because it can have multiple parent terms and multiple child terms but
 * a child term is never also a parent term (and is thius acyclic).
 * Each term stores a list of it's own parent terms.
 * @author Jamie MacPherson
 */
public class GoTerm extends DAG implements Comparable{

    // a unique identifier of the GO term
    private int id;

    //an optional name of the GO term
    private String name;

    // a list of the parent terms of the GO term
    private List<GoTerm> parents = new ArrayList<GoTerm>();

    /**
     * @param id instantiate a GoTerm with a unique identifier.
     */
    public GoTerm(int id) {
        super();
        this.id = id;
    }

    /**
     *
     * @param name sets the name of the GO term
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     * @return gets the name of the GO term
     */
    public String getName() {
        return name;
    }

    /**
     *
     * @param gt add a parent to the list of parents for this GO term
     */
    public void addParent(GoTerm gt){
        if(!parents.contains(gt)){
            parents.add(gt);
        }
    }
    /**
    *
    * @return a list of the parents of this GO term
    */
    public List<GoTerm> getParents() {
        return parents;
    }
    

    /**
     * this GO term is equal to another DAG node GO term if if has the same
     * unique identifier.
     * @param another DAG
     * @return true if equal, false if not.
     */
    @Override
    protected boolean nodeEqual(DAG g) {

        GoTerm other = (GoTerm) g;
        return (other.getId()==this.getId());

    }

    /**
     *
     * @return a new GO term with the same ID.
     */
    @Override
    protected DAG nodeCopy() {
        return new GoTerm(id);
    }

    /**
     * @return the unique GO term identifier
     */
    public int getId() {
        return id;
    }

    /**
     * returns the same result as the <code>nodeEqual(dag)</code> method.
     * @param obj an object to test for equality
     */
    @Override
    public boolean equals(Object obj){
        return nodeEqual((GoTerm) obj);
    }

    public int compareTo(Object o) {
        GoTerm otherTerm = (GoTerm) o;
        return new Integer(this.getId()).compareTo(otherTerm.getId());
    }

    public boolean isDescendedFrom(GoTerm otherTerm){
        if(this.equals(otherTerm)){
            return true;
        }
        HashSet<GoTerm> allParents = new HashSet<GoTerm>();
        addAllParents(this, allParents);
        if(allParents.contains(otherTerm)){
            return true;
        }
        return false;

    }

    private void addAllParents(GoTerm term, HashSet<GoTerm> parents) {
        for(GoTerm p : term.getParents()){
            if(!parents.contains(p)){
                parents.add(p);
                addAllParents(p, parents);
            }
        }

    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 71 * hash + this.id;
        return hash;
    }

    






}
